using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace Pokemon
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class ZNormalHat : Zombie
    {
        public ZNormalHat(Game game, Blank owner, Vector2 position) 
            : base(game, owner, position)
        {
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            XDocument doc = XDocument.Load(@"Content/Textures/Zombies/ZNormalHat/ZNormalHatDef.xml");
            Texture2D texture2;
            Vector2 frameSize = Vector2.Zero;
            Vector2 centerPoint = Vector2.Zero;
            int numFrame;

            XName name = XName.Get(@"FrameWidth");
            if (doc.Document != null)
            {
                var definitions = doc.Document.Descendants(name);
                Int32 frameWidth = Int32.Parse((definitions.First()).Value);

                name = XName.Get(@"FrameHeight");
                definitions = doc.Document.Descendants(name);
                Int32 frameHeight = Int32.Parse((definitions.First()).Value);
                Size = new Vector2(frameWidth, frameHeight);

                name = XName.Get("Damages");
                definitions = doc.Document.Descendants(name);
                Damage = Int32.Parse((definitions.First()).Value);

                name = XName.Get("Healths");
                definitions = doc.Document.Descendants(name);
                _health = Int32.Parse((definitions.First()).Value);

                name = XName.Get("Speed");
                definitions = doc.Document.Descendants(name);
                _speed = Int32.Parse((definitions.First()).Value);

                name = XName.Get(@"Range");
                definitions = doc.Document.Descendants(name);
                _range = Int32.Parse(definitions.First().Value);

                name = XName.Get(@"Definition");
                definitions = doc.Document.Descendants(name);
                foreach (var definition in definitions)
                {
                    var xAttribute = definition.Attribute(@"SheetName");
                    texture2 = Game.Content.Load<Texture2D>(xAttribute.Value);
                    xAttribute = definition.Attribute(@"FrameWidth");

                    var width = Int32.Parse(xAttribute.Value);
                    xAttribute = definition.Attribute(@"FrameHeight");

                    var height = Int32.Parse(xAttribute.Value);
                    frameSize = new Vector2(width, height);
                    xAttribute = definition.Attribute(@"XCenterPoint");

                    var xCenterPoint = Int32.Parse(xAttribute.Value);
                    xAttribute = definition.Attribute(@"YCenterPoint");

                    var yCenterPoint = Int32.Parse(xAttribute.Value);

                    centerPoint = new Vector2(xCenterPoint, yCenterPoint);

                    xAttribute = definition.Attribute(@"NumFrame");
                    numFrame = Int32.Parse(xAttribute.Value);

                    xAttribute = definition.Attribute(@"Name");
                    var type = xAttribute.Value;

                    Sprite sprite = new Sprite(texture2, numFrame, frameSize, centerPoint, false);

                    switch (type)
                    {
                        case "Idle":
                            Textures[0] = sprite;
                            break;
                        case "Attack":
                            Textures[1] = sprite;
                            break;
                        case "Hit":
                            Textures[2] = sprite;
                            break;
                        case "Dead":
                            Textures[3] = sprite;
                            break;
                        case "Stand":
                            Textures[4] = sprite;
                            break;
                    } 
                }
            }
            NormalizePosition();
            base.Initialize();
        }

        public override void TakeDamage(int damage, Color color)
        {
            _health -= damage;
            _Color = color;
        }

        public override void Update(GameTime gameTime)
        {
            _TimeSpan += gameTime.ElapsedGameTime;

            if (_TimeSpan.Milliseconds < 100)
                return;

            if (_health <= 0 && _TimeSpan.Milliseconds < 100)
                return;

            base.Update(gameTime);

            _TimeSpan = TimeSpan.Zero;            

            _position.X -= _speed / 1000;

            if (_health <= 0)
            {
                if (_UnitState == UnitState.Dead)
                {
                    if (Textures[GetUnitStateIndex()].FrameIndex >= 10)
                    {                        
                        CreateBoom();
                        ((GameplayScreen)(_owner.Owner.Owner)).UnitDestroy(this);
                        return;
                    }
                }
                else
                {
                    Dead();
                }
            }

            if (_enemy != null)
            {
                if (Blank.GetDistance(GetCenterPoint(), _enemy.GetCenterPoint()) < _range)
                {
                    if (_UnitState == UnitState.Idle)
                        Attack();
                    else
                        if (Textures[GetUnitStateIndex()].FrameIndex == 4)
                            _enemy.TakeDamage(Damage, Color.White);
                    _position.X += _speed / 1000;
                }
                else
                    if (_UnitState == UnitState.Attack)
                        Idle();
            }
            else
            {
                if (_UnitState == UnitState.Attack)
                    Idle();
            }
            Textures[GetUnitStateIndex()].Update();
        }
        /// <summary>
        /// Lay diem center cua zombie
        /// </summary>
        /// <returns></returns>
        public override Point GetCenterPoint()
        {
            int index = GetUnitStateIndex();
            return new Point((int)_position.X + /*(int)_frameSize[index].X - */(int)Textures[index].CenterPoint.X,
                (int)_position.Y + (int)Textures[index].CenterPoint.Y);
        }

        /// <summary>
        /// Huy doi tuong
        /// </summary>
        /// <param name="disposing"></param>

        protected override void Dispose(bool disposing)
        {
            GameScreen gc = Owner.Owner.Owner;
            if (gc is GameplayScreen)
                ((GameplayScreen)gc).OnZombieDead();
            base.Dispose(disposing);
        }

        /// <summary>
        /// Draw sprite on screen
        /// </summary>
        /// <param name="gameTime"></param>
        public override void Draw(GameTime gameTime)
        {
            Rectangle rect = GetNextRect();
            SpriteBatch _SpriteBatch = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));

            Vector2 ownerEndPoint = Vector2.Zero;
            if (_owner != null)
            {
                ownerEndPoint = new Vector2(_owner.Position.X + _owner.Size.X, _owner.Position.Y + _owner.Size.Y);

                Vector2 position = new Vector2(ownerEndPoint.X - _size.X, ownerEndPoint.Y - _size.Y);
                int index = GetUnitStateIndex();
                Textures[index].Draw(_SpriteBatch, new Vector2(_position.X, position.Y) + new Vector2(0, -12),
                    rect, Color.White, 0, Vector2.Zero, 1.0f, SpriteEffects.None, 0);
            }
            base.Draw(gameTime);
        }


        /// <summary>
        /// Trang thai tan cong cua zombie
        /// </summary>
        public void Attack()
        {
            var prevIndex = GetUnitStateIndex();
            _UnitState = UnitState.Attack;
            var index = GetUnitStateIndex();
            Size = Textures[index].Size;
            float detY = Textures[prevIndex].Size.Y - Size.Y;
            float detX = Textures[prevIndex].Size.X - Size.X;
            Position = Position + new Vector2(detX, detY) + new Vector2(0, 15);
            _textures[prevIndex].Reset();
            _textures[index].Reset();
        }

        /// <summary>
        /// Trang thai di chuyen/dung yen cua zombie       
        /// </summary>
        public void Idle()
        {            
            var prevIndex = GetUnitStateIndex();
            _UnitState = UnitState.Idle;
            var index = GetUnitStateIndex();
            Size = Textures[index].Size;
            float detY = Textures[prevIndex].Size.Y - Size.Y;
            float detX = Textures[prevIndex].Size.X - Size.X;
            Position = Position + new Vector2(detX, detY) - new Vector2(0, 15);
            _textures[prevIndex].Reset();
            _textures[index].Reset();
        }

        /// <summary>
        /// Trang thai zombie bi het mau va chet
        /// </summary>
        public void Dead()
        {            
            var prevIndex = GetUnitStateIndex();
            _UnitState = UnitState.Dead;
            var index = GetUnitStateIndex();
            Size = Textures[index].Size;
            float detY = Textures[prevIndex].Size.Y - Size.Y;
            float detX = Textures[prevIndex].Size.X - Size.X;
            Position = Position + new Vector2(detX, detY) - new Vector2(0, 15);
            _textures[prevIndex].Reset();
            _textures[index].Reset();
        }

        public override void NormalizePosition()
        {
            var ownerEndPoint = new Vector2(_owner.Position.X + _owner.Size.X, _owner.Position.Y + _owner.Size.Y);

            Vector2 position = new Vector2(ownerEndPoint.X - _size.X, ownerEndPoint.Y - _size.Y);

            _position = new Vector2(_position.X, position.Y) + new Vector2(0, -12);
        }
    }
}
